using System.Collections.Generic;
using System;


namespace MSP.Graph
{
    public class Node : INode
    {
        #region Properties

        private object m_data;
        private int m_index;
        private List<Edge> m_edges;
        private Queue<Message> m_incomingMessages;
               
        #endregion  // Properties


        #region Constructor

        public Node(int index, object data, List<Edge> edges)
        {
            m_index = index;
            m_data = data;
            m_edges = edges;

            m_incomingMessages = new Queue<Message>();
        }

        #endregion  // Constructor


        #region Functions

        public void AddEdge(Edge edge)
        {
            m_edges.Add(edge);
        }


        public int GetIndex()
        {
            return m_index;
        }


        public void SetIndex(int index)
        {
            m_index = index;
        }


        public object GetValue()
        {
            return m_data;
        }


        public void SetValue(object data)
        {
            m_data = data;
        }
        

        public IEnumerator<INode> GetNeighborsList()
        {
            List<INode> neighborsList = new List<INode>();

            // create the neighbors list from the list of edges
            foreach (Edge edge in m_edges)
            {
                neighborsList.Add(edge.GetNeighbor(this));
            }

            return neighborsList.GetEnumerator();
        }


        public IEnumerator<Message> ReceiveMessages()
        {
            // get the queued messages
            IEnumerator<Message> messages = m_incomingMessages.GetEnumerator();
            
            // clear all the messages in the queue
            m_incomingMessages.Clear();

            return messages;
        }


        public void SendMessage(Message message)
        {
            // check that the source of the message is the current node
            if (!(this.Equals(message.FromNode)))
            {
                throw new ArgumentException("Invalid Message Origin");
            }

            // get the target of the message
            Node node = (Node)message.ToNode;

            node.EnqueueIncomingMessage(message);
        }


        private void EnqueueIncomingMessage(Message message)
        {
            m_incomingMessages.Enqueue(message);
        }

        #endregion  // Functions
    }
}
